package com.dao;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.FactoryBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MapperFactoryBean2 implements FactoryBean<Object> {
    private Class<?> mapperClass;
    private SqlSessionFactory factory;

    public SqlSessionFactory getFactory() {
        return factory;
    }

    public void setFactory(SqlSessionFactory factory) {
        this.factory = factory;
    }

    public Class<?> getMapperClass() {
        return mapperClass;
    }

    public void setMapperClass(Class<?> mapperClass) {
        this.mapperClass = mapperClass;
    }

    @Override
    public Object getObject() throws Exception {
        SqlSession sqlSession = getFactory().openSession(true);
        System.out.println("---创建了一个sqlSession hashcode:" + sqlSession.hashCode());
        Object mapper = sqlSession.getMapper(getMapperClass());
        System.out.println("getMapperClass() = " + getMapperClass());
        InvocationHandler invocationHandler = new MapperInvoker(sqlSession, mapper);
        Object mapperProxy = Proxy.newProxyInstance(MapperFactoryBean2.class.getClassLoader(), new Class[]{getMapperClass()}, invocationHandler);
        return mapperProxy;
    }

    @Override
    public Class<?> getObjectType() {
        return mapperClass;
    }

    static class MapperInvoker implements InvocationHandler {
        private Object target;
        private SqlSession sqlSession;

        public MapperInvoker(SqlSession sqlSession, Object target) {
            System.out.println("传进来的sqlsession hashcode：" + sqlSession.hashCode());
            System.out.println("传进来的target hashcode：" + target.hashCode());
            this.sqlSession = sqlSession;
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }
            String name = method.getName();
            System.out.println("---当前调用的方法名:" + name);
            Object result = null;
            try {
                result = method.invoke(target, args);
            } finally {
                System.out.println("准备关闭sqlSession---hashcode:" + sqlSession.hashCode());
                sqlSession.close();
            }
            return result;
        }
    }
}
